import { defineStore } from 'pinia';
import * as Cesium from 'cesium';
function parseColor(colorStr) {
  return [
    parseInt(colorStr.slice(1, 3), 16),
    parseInt(colorStr.slice(3, 5), 16),
    parseInt(colorStr.slice(5, 7), 16)
  ];
}

function interpolateColor(color1, color2, t) {
  if (!color1 || !color2) {
    console.log("color",color1,color2)
    throw new Error('Invalid colors provided for interpolation.');
  }
  return [
    Math.floor(color1[0] + t * (color2[0] - color1[0])),
    Math.floor(color1[1] + t * (color2[1] - color1[1])),
    Math.floor(color1[2] + t * (color2[2] - color1[2]))
  ];
}

// 节流函数
function throttle(fn, wait) {
  let time = Date.now();
  return function(...args) {
    if ((time + wait - Date.now()) < 0) {
      fn.apply(this, args);
      time = Date.now();
    }
  }
}

export const useWenyanStore = defineStore('wenyan', {
  state: () => ({
    viewer: null, // Cesium Viewer 实例
    data: [], // 温盐数据
    colors: ["#2ad587", "#55a666", "#807644", "#807644", "#ab4622", "#d61600"], // 颜色映射
    isVisible: false, // 显隐状态
    primitive: null, // 存储 Primitive 实例
    handler: null, // 事件处理器
    colorMode: 'interpolated', // 颜色模式//interpolated//segmented
    latmin: 15,
    latmax: 25,
    lonmin: 110,
    lonmax: 124,
  }),
  actions: {
    // 设置 Viewer
    setViewer(viewer) {
      this.viewer = viewer;
    },
    setColorMode(colorMode) {
      this.colorMode = colorMode;
    },
    setMaxValue(maxValue) {
      this.maxValue = maxValue;
    },
    setMinValue(minValue) {
      this.minValue = minValue;
    },
    setIsVisible(isVisible) {
      this.isVisible = isVisible; 
    },
    // 设置温盐数据
    setData(data) {
      this.data = data;
    },
    // 设置颜色映射
    setColors(colors) {
      this.colors = colors;
    },

    createPrimitive() {
      let _this = this;
      const instances = [];
      const rgbColors = this.colors.map(parseColor);
      const map = new Map();
      let header =  this.data.header
      let maxValue = this.data.max
      let minValue = this.data.min
      this.data.data.forEach(item => {
        const key = `${item.lon},${item.lat}`;
        map.set(key, item.value);
      });

      function findValueByXAndY(targetLon, targetLat) {
        return map.get(`${targetLon},${targetLat}`);
      }

      function temperatureToColor(currentTemp, mode = 'segmented') {
        if (currentTemp == 9999) return [0, 0, 0, 0];

        currentTemp = Math.min(Math.max(currentTemp, minValue), maxValue);

        if (mode === 'segmented') {
          const segmentSize = (maxValue - minValue) / (rgbColors.length - 1);
          let segmentIndex = Math.floor((currentTemp - _this.minValue) / segmentSize);
          segmentIndex = Math.min(segmentIndex, rgbColors.length - 1);
          const [r, g, b] = rgbColors[segmentIndex];
          return [r, g, b, 1];
        } else if (mode === 'interpolated') {
          const ratio = (currentTemp - minValue) / (maxValue - minValue);
          const index = Math.floor(ratio * (rgbColors.length - 1));
          const t = ratio * (rgbColors.length - 1) - index;
          if (index >= rgbColors.length - 1) {
            const [r, g, b] = rgbColors[rgbColors.length - 1];
            return [r, g, b, 1];
          }
          const [r, g, b] = interpolateColor(rgbColors[index], rgbColors[index + 1], t);
          return [r, g, b, 1];
        }
      }

      function rgbToCesiumColor(r, g, b, a) {
        
        let red = r / 255;
        let green = g / 255;
        let blue = b / 255;
        return new Cesium.Color(red, green, blue, a);
      }

      for (let lon = header.lo1; lon < header.lo2; lon += header.dx) {
        for (let lat = header.la1; lat < header.la2; lat += header.dy) {
          let v = findValueByXAndY(lon, lat);
          let colortemp = temperatureToColor(v, _this.colorMode);
          instances.push(
            new Cesium.GeometryInstance({
              geometry: new Cesium.RectangleGeometry({
                rectangle: Cesium.Rectangle.fromDegrees(lon, lat, lon + header.dx, lat + header.dy),
                vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,
              }),
              id: v,
              attributes: {
                color: Cesium.ColorGeometryInstanceAttribute.fromColor(rgbToCesiumColor(colortemp[0], colortemp[1], colortemp[2], colortemp[3])),
              },
            })
          );
        }
      }

      if (this.primitive) this.viewer.scene.primitives.remove(this.primitive);
      this.primitive = this.viewer.scene.primitives.add(new Cesium.Primitive({
        geometryInstances: instances,
        appearance: new Cesium.PerInstanceColorAppearance(),
      }));
      this.addMouseMoveHandler();
    },

    addMouseMoveHandler() {
      if (!this.viewer || !this.primitive) return;

      if (this.handler) this.handler.destroy();
      this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
      
      this.handler.setInputAction(throttle((movement) => {
        const ray = this.viewer.camera.getPickRay(movement.endPosition);
        var pick = this.viewer.scene.pick(movement.endPosition);
        if (!ray) return;

        const cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
        if (!cartesian) return;

        const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
        const lon = Cesium.Math.toDegrees(cartographic.longitude);
        const lat = Cesium.Math.toDegrees(cartographic.latitude);

        let value = null;
        if (Cesium.defined(pick)) value = pick.id;
        
        if (value == null) {
          this.emitTemplatureOrSalt(null);
        } else {
          this.emitTemplatureOrSalt({
            lon: lon.toFixed(4),
            lat: lat.toFixed(4),
            value: value.toFixed(4),
            name: ""
          });
        }
      }, 50), Cesium.ScreenSpaceEventType.MOUSE_MOVE); // 每50ms最多触发一次
    },
      // 触发事件，传递海流信息
      emitTemplatureOrSalt(data) {
    const event = new CustomEvent('templatureOrSalt', { detail: data });
    window.dispatchEvent(event);
  },
    toggleWenyanVisibility() {
      this.isVisible = !this.isVisible;
      if (this.isVisible) {
        this.createPrimitive();
      } else {
        if (this.primitive) {
          this.viewer.scene.primitives.remove(this.primitive);
          this.primitive = null;
        }
        if (this.handler) {
          this.handler.destroy();
          this.handler = null;
        }
      }
    },
  },
});